package com.zllkj.mm.api.network;


import android.content.Context;
import android.util.Log;

import com.zllkj.mm.AppManager;
import com.zllkj.mm.api.network.exception.ApiException;
import com.zllkj.mm.api.network.subscriber.ProgressSubscriber;
import com.zllkj.mm.common.L;
import com.zllkj.mm.rx.FragmentEvent;

import java.util.concurrent.TimeUnit;

import retrofit2.Response;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject;

public class RxHelper {

    /**
     * 统一返回结果处理
     *
     * @param <T>
     * @return
     */
    public static <T> Observable.Transformer<BaseResponse<T>, T> defaultHandleResult() {   //compose判断结果
        return new Observable.Transformer<BaseResponse<T>, T>() {
            @Override
            public Observable<T> call(Observable<BaseResponse<T>> tObservable) {
                return tObservable.flatMap(new Func1<BaseResponse<T>, Observable<T>>() {
                    @Override
                    public Observable<T> call(BaseResponse<T> result) {
                        if (result.getCode() == 1 || result.getCode() == 11) {
                            if (result.getCode() == 11){
                                AppManager.getAppManager().currentActivity().runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Log.d("acthome","toast error");
                                        L.showToast(result.getMessage());
                                    }
                                });
                            }
                            return createData(result.result);
                        } else {
                            Log.d("acthome"," error 3333");
                            return Observable.error(new ApiException(result.getCode(),
                                    result.getMessage()));
                        }
                    }
                }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).single();
            }

        };
    }

    /**
     * 统一返回结果处理
     *
     * @param <T>
     * @return
     */
    public static <T> Observable.Transformer<BaseResponse<T>, T> defaultHandleListResult() {   //compose判断结果
        return new Observable.Transformer<BaseResponse<T>, T>() {
            @Override
            public Observable<T> call(Observable<BaseResponse<T>> tObservable) {
                return tObservable.flatMap(new Func1<BaseResponse<T>, Observable<T>>() {
                    @Override
                    public Observable<T> call(BaseResponse<T> result) {
                        if (result.getCode() == 1 || result.getCode() == 11) {
                            if (result.getCode() == 11){
                                AppManager.getAppManager().currentActivity().runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        L.showToast(result.getMessage());
                                    }
                                });
                            }
                            return createData(result.result);
                        } else {
                            return Observable.error(new ApiException(result.getCode(),
                                    result.getMessage()));
                        }
                    }
                }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).single();
            }

        };
    }


    /**
     * 统一线程处理
     *
     * @param <T>
     * @return
     */
    public static <T> Observable.Transformer<T, T> rxSchedulerHelper() {    //compose简化线程
        return new Observable.Transformer<T, T>() {
            @Override
            public Observable<T> call(Observable<T> observable) {
                return observable.subscribeOn(Schedulers.io())
                        .unsubscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread()).single();
            }
        };
    }


    /**
     * 创建成功的数据
     *
     * @param data
     * @param <T>
     * @return
     */
    private static <T> Observable<T> createData(final T data) {
        return Observable.create(new Observable.OnSubscribe<T>() {
            @Override
            public void call(Subscriber<? super T> subscriber) {
                try {
                    subscriber.onNext(data);
                    subscriber.onCompleted();
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }
        });

    }


    public static <T> void toSubscribe(Observable<T> ob, Subscriber<T> s) {
        ob.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(s);
    }

    /**
     * 添加线程管理并订阅
     */
    public static void toSubscribeV2(Observable ob, final ProgressSubscriber subscriber, final FragmentEvent event, final PublishSubject<FragmentEvent> lifecycleSubject) {
        //数据预处理
        Observable.Transformer<BaseResponse<Object>, Object> result = RxHelper.handleResultV2(event, lifecycleSubject);
        Observable observable = ob.compose(result)
                .doOnSubscribe(new Action0() {
                    @Override
                    public void call() {
                        //显示Dialog和一些其他操作
//                        subscriber.showProgressDialog();
                    }
                });
//        RetrofitCache.load(cacheKey,observable,isSave,forceRefresh).subscribe(subscriber);
//        observable.compose(RxHelper.rxSchedulerHelper())
//                .subscribe(subscriber);


    }


    public static <T> Observable.Transformer<BaseResponse<T>, T> handleResultV2(final FragmentEvent event, final PublishSubject<FragmentEvent> lifecycleSubject) {
        return new Observable.Transformer<BaseResponse<T>, T>() {
            @Override
            public Observable<T> call(Observable<BaseResponse<T>> tObservable) {
                Observable<FragmentEvent> compareLifecycleObservable =
                        lifecycleSubject.takeFirst(new Func1<FragmentEvent, Boolean>() {
                            @Override
                            public Boolean call(FragmentEvent activityLifeCycleEvent) {
                                return activityLifeCycleEvent.equals(event);
                            }
                        });
                return tObservable.flatMap(new Func1<BaseResponse<T>, Observable<T>>() {
                    @Override
                    public Observable<T> call(BaseResponse<T> result) {
                        if (result.getCode() == 0) {
                            return createData(result.getResult());
                        } else {
                            return Observable.error(new ApiException(result.getCode(), result.getMessage()));
                        }
                    }
                }).takeUntil(compareLifecycleObservable).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).subscribeOn(AndroidSchedulers.mainThread()).observeOn(AndroidSchedulers.mainThread());
            }
        };
    }


    /**
     * 这里就不细讲了,具体可以去看rxjava的使用.这个类的意义就是转换Observable.
     */
    private static class SimpleTransformer<T> implements Observable.Transformer<BaseResponse<T>, T> {
        //这里对Observable,进行一般的通用设置.不用每次用Observable都去设置线程以及重连设置
        @Override
        public Observable<T> call(Observable<BaseResponse<T>> observable) {
            return observable.subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .unsubscribeOn(Schedulers.io())
                    .timeout(5, TimeUnit.SECONDS)//重连间隔时间
                    .retry(5)//重连次数
                    .flatMap(new Func1<BaseResponse<T>, Observable<T>>() {
                        @Override
                        public Observable<T> call(BaseResponse<T> tBaseResponse) {
                            return flatResponse(tBaseResponse);
                        }
                    });
        }

        /**
         * 处理请求结果,BaseResponse
         *
         * @param response 请求结果
         * @return 过滤处理, 返回只有data数据的Observable
         */
        private Observable<T> flatResponse(final BaseResponse<T> response) {
            return Observable.create(new Observable.OnSubscribe<T>() {
                @Override
                public void call(Subscriber<? super T> subscriber) {
                    if (response.getCode() == 0) {//请求成功
                        if (!subscriber.isUnsubscribed()) {
                            subscriber.onNext(response.getResult());
                        }
                    } else {//请求失败
                        if (!subscriber.isUnsubscribed()) {
                            //这里抛出自定义的一个异常.可以处理服务器返回的错误.
                            subscriber.onError(new ApiException(response.getCode(),
                                    response.getMessage()));
                        }
                        return;
                    }
                    if (!subscriber.isUnsubscribed()) {//请求完成
                        subscriber.onCompleted();
                    }
                }
            });
        }
    }


    public static class SchedulerTransformer<T> implements Observable.Transformer<T, T> {
        @Override
        public Observable<T> call(Observable<T> observable) {
            return observable
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread());
        }

        public static <T> SchedulerTransformer<T> create() {
            return new SchedulerTransformer<>();
        }
    }

    public static class ErrorCheckerTransformer<T extends Response<R>, R extends BaseResponse>
            implements Observable.Transformer<T, R> {

        public static final String DEFAULT_ERROR_MESSAGE = "Oh, no";

        private Context mContext;

        public ErrorCheckerTransformer(final Context context) {
            mContext = context;
        }

        @Override
        public Observable<R> call(Observable<T> observable) {
            return observable.map(new Func1<T, R>() {
                @Override
                public R call(T t) {
                    String msg = null;
//                    if (!t.isSuccessful() || t.body() == null) {
//                        msg = DEFAULT_ERROR_MESSAGE;
//                    } else if (t.body().errorResponse != null) {
//                        msg = t.body().errorResponse.msg;
//                        if (msg == null) {
//                            msg = DEFAULT_ERROR_MESSAGE;
//                        }
//                    } else if (t.body().code != BaseResponse.CODE_SUCCESS) {
//                        msg = t.body().msg;
//                        if (msg == null) {
//                            msg = DEFAULT_ERROR_MESSAGE;
//                        }
//                    }
//
//                    if (msg != null) {
//                        try {
//                            throw new ErrorResponseException(msg);
//                        } catch (ErrorResponseException e) {
//                            throw Exceptions.propagate(e);
//                        }
//                    }

                    return t.body();
                }
            });
        }
    }


    public static class DefaultTransformer<T extends Response<R>, R extends BaseResponse>
            implements Observable.Transformer<T, R> {

        private Context mContext;

        public DefaultTransformer(final Context context) {
            mContext = context;
        }

        @Override
        public Observable<R> call(Observable<T> observable) {
            return observable
                    .compose(new SchedulerTransformer<T>())
                    .compose(new ErrorCheckerTransformer<T, R>(mContext));
        }
    }


    public static Observable.Transformer schedulersTransformer = new Observable.Transformer() {
        @Override
        public Object call(Object observable) {
            return ((Observable) observable).subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread());
        }
    };


    public static <T> Observable.Transformer<BaseResponse<T>, T> transformer() {

        return new Observable.Transformer() {

            @Override
            public Object call(Object observable) {
                return ((Observable) observable).map(new Func1<BaseResponse<T>, T>() {
                    @Override
                    public T call(BaseResponse<T> response) {
                        if (response.getCode() != 0)
                            throw new RuntimeException(response.getCode() + "" + response.getMessage() != null ? response.getMessage() : "");
                        return response.getResult();
                    }
                }).onErrorResumeNext(new Func1<Throwable, Observable<T>>() {
                    @Override
                    public Observable<T> call(Throwable t) {
                        return Observable.error(ExceptionHandle.handleException(t));
                    }
                });
            }
        };
    }


    /**
     * 统一返回结果处理
     * @param <T>
     * @return
     */
//    public static <T> Observable.Transformer<BaseResponse<T>, T> handleResult() {   //compose判断结果
//        return new Observable.Transformer<BaseResponse<T>, T>() {
//            @Override
//            public Observable<T> call(Observable<BaseResponse<T>> tObservable) {
//                return tObservable.flatMap(new Func1<BaseResponse<T>, Observable<T>>() {
//                    @Override
//                    public Observable<T> call(BaseResponse<T> result) {
//                        if(result.code == 0) {
//                            return createData(result.data);
//                        } else {
//                            return Observable.error(new ApiException(result.code, result.msg));
//                        }
//                    }
//                });
//            }
//        };
//    }


}
